<script setup>
import { ref, reactive, shallowRef, shallowReactive, markRaw, toRaw, isReactive, isRef, isProxy, watchEffect } from 'vue';

// 代码示例常量定义
const shallowRefExampleCode = `// 创建浅层响应式引用
const shallowUserRef = shallowRef({
  name: '张三',
  address: { city: '北京' }
});

// 直接修改嵌套属性不会触发更新
shallowUserRef.value.address.city = '上海';

// 需要替换整个对象才会触发更新
shallowUserRef.value = {
  ...shallowUserRef.value,
  address: { ...shallowUserRef.value.address, city: '上海' }
};

// 创建浅层响应式对象
const shallowProduct = shallowReactive({
  id: 1,
  name: '产品',
  specs: { cpu: 'Intel' }
});

// 顶层属性更新会触发响应
shallowProduct.name = '新产品';

// 嵌套属性更新不会触发响应
shallowProduct.specs.cpu = 'AMD';`;

const markRawExampleCode = `// 创建非响应式对象
const nonReactiveLib = markRaw({
  version: '1.0.0',
  // 大型第三方库实例...
});

// 在响应式对象中使用非响应式数据
const appState = reactive({
  name: '应用',
  library: nonReactiveLib
});

// 获取响应式对象的原始对象
const originalState = reactive({ count: 0 });
const rawState = toRaw(originalState);

// 修改原始对象不会触发响应式更新
rawState.count++;  // 不会触发更新

// 仍然可以通过原始响应式对象更新
originalState.count++;  // 会触发更新`;

// 常量定义示例代码
const scenariosExampleCode = `// 适用场景示例
const scenarios = [
  {
    api: 'shallowRef',
    scenarios: [
      '大型不可变对象或第三方库实例',
      '仅关心对象整体替换而不是内部属性变化',
      '性能敏感场景，避免深度响应式转换的开销'
    ]
  },
  {
    api: 'shallowReactive',
    scenarios: [
      '表单状态管理，只需响应顶层字段变化',
      '大型状态树，仅关心第一层属性变化',
      'UI状态管理，如对话框、抽屉等组件的可见性'
    ]
  },
  {
    api: 'markRaw',
    scenarios: [
      '集成第三方库实例（如Chart.js、D3.js等）',
      '避免响应式转换的性能开销',
      '防止Vue拦截某些特定对象的访问'
    ]
  },
  {
    api: 'toRaw',
    scenarios: [
      '临时获取原始数据进行性能优化操作',
      '将响应式数据传递给不支持Proxy的第三方库',
      '避免在某些操作中触发不必要的响应式更新'
    ]
  }
];`;

const commonMistakesExampleCode = `// 错误使用示例
const commonMistakes = [
  {
    api: 'shallowRef',
    mistake: '期望修改嵌套属性时触发视图更新',
    solution: '修改嵌套属性后，使用shallowRef.value = { ...shallowRef.value } 或改用ref'
  },
  {
    api: 'shallowReactive',
    mistake: '在计算属性或watch中依赖嵌套属性',
    solution: '确保只依赖浅层属性，或改用reactive'
  },
  {
    api: 'markRaw',
    mistake: '标记需要响应式更新的数据',
    solution: '只对确实不需要响应式的数据使用markRaw'
  },
  {
    api: 'toRaw',
    mistake: '直接修改toRaw返回的对象并期望触发更新',
    solution: '仅用于读取操作，修改操作应在原始响应式对象上进行'
  }
];`;

// 常量定义
// 适用场景示例
const scenarios = [
  {
    api: 'shallowRef',
    scenarios: [
      '大型不可变对象或第三方库实例',
      '仅关心对象整体替换而不是内部属性变化',
      '性能敏感场景，避免深度响应式转换的开销'
    ]
  },
  {
    api: 'shallowReactive',
    scenarios: [
      '表单状态管理，只需响应顶层字段变化',
      '大型状态树，仅关心第一层属性变化',
      'UI状态管理，如对话框、抽屉等组件的可见性'
    ]
  },
  {
    api: 'markRaw',
    scenarios: [
      '集成第三方库实例（如Chart.js、D3.js等）',
      '避免响应式转换的性能开销',
      '防止Vue拦截某些特定对象的访问'
    ]
  },
  {
    api: 'toRaw',
    scenarios: [
      '临时获取原始数据进行性能优化操作',
      '将响应式数据传递给不支持Proxy的第三方库',
      '避免在某些操作中触发不必要的响应式更新'
    ]
  }
];

// 错误使用示例
const commonMistakes = [
  {
    api: 'shallowRef',
    mistake: '期望修改嵌套属性时触发视图更新',
    solution: '修改嵌套属性后，使用shallowRef.value = { ...shallowRef.value } 或改用ref'
  },
  {
    api: 'shallowReactive',
    mistake: '在计算属性或watch中依赖嵌套属性',
    solution: '确保只依赖浅层属性，或改用reactive'
  },
  {
    api: 'markRaw',
    mistake: '标记需要响应式更新的数据',
    solution: '只对确实不需要响应式的数据使用markRaw'
  },
  {
    api: 'toRaw',
    mistake: '直接修改toRaw返回的对象并期望触发更新',
    solution: '仅用于读取操作，修改操作应在原始响应式对象上进行'
  }
];

// 基础响应式状态
const basicCount = ref(0);
const basicState = reactive({ name: 'Vue 3', version: '3.3+' });

// 高级响应式API演示
// 1. shallowRef - 只对.value的变更做出响应
const shallowUserRef = shallowRef({
  name: '张三',
  address: { city: '北京', district: '朝阳区' }
});

// 2. shallowReactive - 仅响应第一层属性的变化
const shallowProduct = shallowReactive({
  id: 1,
  name: '笔记本电脑',
  specs: {
    cpu: 'Intel i7',
    memory: '16GB'
  }
});

// 3. markRaw - 标记对象使其永远不会被转换为响应式
const nonReactiveData = markRaw({
  framework: 'Vue',
  createdBy: 'Evan You',
  contributors: 3000
});

const appData = reactive({
  name: 'My App',
  // 这个对象不会被转换为响应式
  meta: nonReactiveData
});

// 4. toRaw - 获取响应式对象的原始对象
const originalBasicState = toRaw(basicState);

// 测试函数
const incrementBasic = () => {
  basicCount.value++;
};

const updateBasicState = () => {
  basicState.version = `3.${Math.floor(Math.random() * 10)}.${Math.floor(Math.random() * 100)}`;
};

const updateShallowRef = () => {
  // 直接修改shallowRef的嵌套属性不会触发更新
  shallowUserRef.value.address.city = '上海';
  console.log('嵌套属性已修改，但视图不会更新');
};

const replaceShallowRef = () => {
  // 替换整个对象会触发更新
  shallowUserRef.value = {
    ...shallowUserRef.value,
    address: { ...shallowUserRef.value.address, city: '上海' }
  };
};

const updateShallowReactive = () => {
  // 更新第一层属性会触发更新
  shallowProduct.name = '台式电脑';
};

const updateNestedSpecs = () => {
  // 更新嵌套属性不会触发更新
  shallowProduct.specs.cpu = 'AMD Ryzen 7';
  console.log('嵌套specs已修改，但视图不会更新');
};

const replaceSpecs = () => {
  // 替换整个嵌套对象会触发更新
  shallowProduct.specs = { ...shallowProduct.specs, cpu: 'AMD Ryzen 7' };
};

const tryModifyNonReactive = () => {
  // 尝试修改nonReactiveData不会触发响应式更新
  appData.meta.contributors = Math.floor(Math.random() * 5000);
  console.log('非响应式数据已修改，但视图不会更新');
};

// 响应式检查
const checkReactivity = () => {
  const checks = {
    basicCount: isRef(basicCount),
    basicState: isReactive(basicState),
    shallowUserRef: isRef(shallowUserRef),
    shallowProduct: isReactive(shallowProduct),
    appData: isProxy(appData),
    appDataMeta: isReactive(appData.meta),
    originalBasicState: isReactive(originalBasicState)
  };
  console.table(checks);
};

// 性能监控演示
const performanceResults = ref({
  reactiveTime: 0,
  shallowReactiveTime: 0,
  refTime: 0,
  shallowRefTime: 0
});

const runPerformanceTest = () => {
  const largeObject = generateLargeObject(1000);

  // 测试reactive性能
  const startReactive = performance.now();
  const reactiveObj = reactive(largeObject);
  const endReactive = performance.now();

  // 测试shallowReactive性能
  const startShallowReactive = performance.now();
  const shallowReactiveObj = shallowReactive(largeObject);
  const endShallowReactive = performance.now();

  // 测试ref性能
  const startRef = performance.now();
  const refObj = ref(largeObject);
  const endRef = performance.now();

  // 测试shallowRef性能
  const startShallowRef = performance.now();
  const shallowRefObj = shallowRef(largeObject);
  const endShallowRef = performance.now();

  performanceResults.value = {
    reactiveTime: (endReactive && startReactive) ? (endReactive - startReactive).toFixed(2) : '0.00',
    shallowReactiveTime: (endShallowReactive && startShallowReactive) ? (endShallowReactive - startShallowReactive).toFixed(2) : '0.00',
    refTime: (endRef && startRef) ? (endRef - startRef).toFixed(2) : '0.00',
    shallowRefTime: (endShallowRef && startShallowRef) ? (endShallowRef - startShallowRef).toFixed(2) : '0.00'
  };
};

const generateLargeObject = (depth) => {
  const obj = {};
  for (let i = 0; i < depth; i++) {
    obj[`key${i}`] = {
      value: i,
      nested: { data: `nested-data-${i}` }
    };
  }
  return obj;
};
</script>

<template>
  <div class="reactive-advanced-demo">
    <h2 class="demo-title">🔄 Vue 3 响应式系统高级特性</h2>

    <p class="demo-description">
      Vue 3提供了丰富的响应式API，除了基础的ref和reactive外，还有shallowRef、shallowReactive、markRaw等高级API，
      用于不同场景下的性能优化和特殊需求处理。
    </p>

    <!-- 基础响应式对比 -->
    <div class="demo-section">
      <h3>基础响应式 vs 高级响应式</h3>

      <div class="comparison-grid">
        <!-- 基础ref -->
        <div class="demo-card">
          <h4>基础 ref</h4>
          <p>Count: {{ basicCount }}</p>
          <button @click="incrementBasic" class="btn">增加</button>
        </div>

        <!-- 基础reactive -->
        <div class="demo-card">
          <h4>基础 reactive</h4>
          <p>{{ JSON.stringify(basicState) }}</p>
          <button @click="updateBasicState" class="btn">更新版本</button>
        </div>

        <!-- shallowRef -->
        <div class="demo-card">
          <h4>shallowRef</h4>
          <p>{{ JSON.stringify(shallowUserRef.value) }}</p>
          <div class="btn-group">
            <button @click="updateShallowRef" class="btn btn-warning">修改嵌套属性（无更新）</button>
            <button @click="replaceShallowRef" class="btn btn-primary">替换整个对象</button>
          </div>
        </div>

        <!-- shallowReactive -->
        <div class="demo-card">
          <h4>shallowReactive</h4>
          <p>{{ JSON.stringify(shallowProduct) }}</p>
          <div class="btn-group">
            <button @click="updateShallowReactive" class="btn btn-primary">更新顶层属性</button>
            <button @click="updateNestedSpecs" class="btn btn-warning">修改嵌套属性（无更新）</button>
            <button @click="replaceSpecs" class="btn btn-success">替换嵌套对象</button>
          </div>
        </div>

        <!-- markRaw -->
        <div class="demo-card">
          <h4>markRaw</h4>
          <p>App Data: {{ appData.name }}</p>
          <p>Meta: {{ JSON.stringify(appData.meta) }}</p>
          <button @click="tryModifyNonReactive" class="btn btn-warning">修改非响应式数据</button>
        </div>
      </div>
    </div>

    <!-- 响应式检查 -->
    <div class="demo-section">
      <h3>响应式状态检查</h3>
      <p>使用Vue提供的工具函数检查数据是否为响应式</p>
      <button @click="checkReactivity" class="btn">运行检查</button>
      <p class="hint">检查结果将输出到控制台</p>
    </div>

    <!-- 性能对比 -->
    <div class="demo-section">
      <h3>性能对比测试</h3>
      <p>对比不同响应式API的初始化性能（基于1000个嵌套对象）</p>
      <button @click="runPerformanceTest" class="btn btn-primary">运行性能测试</button>

      <div v-if="performanceResults.reactiveTime > 0" class="performance-results">
        <table class="performance-table">
          <thead>
            <tr>
              <th>API</th>
              <th>初始化时间 (ms)</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>reactive</td>
              <td>{{ performanceResults.reactiveTime }}</td>
            </tr>
            <tr>
              <td>shallowReactive</td>
              <td>{{ performanceResults.shallowReactiveTime }}</td>
            </tr>
            <tr>
              <td>ref</td>
              <td>{{ performanceResults.refTime }}</td>
            </tr>
            <tr>
              <td>shallowRef</td>
              <td>{{ performanceResults.shallowRefTime }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- 使用场景 -->
    <div class="demo-section">
      <h3>适用场景</h3>

      <div class="scenarios-grid">
        <div v-for="item in scenarios" :key="item.api" class="scenario-card">
          <h4 class="scenario-api">{{ item.api }}</h4>
          <ul class="scenario-list">
            <li v-for="(scenario, index) in item.scenarios" :key="index">
              {{ scenario }}
            </li>
          </ul>
        </div>
      </div>
    </div>

    <!-- 常见错误 -->
    <div class="demo-section">
      <h3>常见错误及解决方案</h3>

      <div class="mistakes-grid">
        <div v-for="(mistake, index) in commonMistakes" :key="index" class="mistake-card">
          <h4>{{ mistake.api }}</h4>
          <div class="mistake-content">
            <p class="mistake-text">❌ {{ mistake.mistake }}</p>
            <p class="solution-text">✅ {{ mistake.solution }}</p>
          </div>
        </div>
      </div>
    </div>

    <!-- 最佳实践 -->
    <div class="demo-section">
      <h3>最佳实践</h3>

      <div class="best-practices">
        <ul>
          <li>优先使用 <code>ref</code> 和 <code>reactive</code>，仅在有明确性能需求时使用浅层API</li>
          <li>对于大型对象，考虑使用 <code>shallowReactive</code> 或 <code>shallowRef</code> 优化性能</li>
          <li>第三方库实例应使用 <code>markRaw</code> 避免不必要的响应式转换</li>
          <li>在性能敏感的操作中，使用 <code>toRaw</code> 获取原始数据进行批量处理</li>
          <li>注意浅层响应式API的限制，避免在依赖嵌套属性的场景中使用</li>
          <li>在组件卸载时，确保清理所有定时器和事件监听器，避免内存泄漏</li>
        </ul>
      </div>
    </div>

    <!-- 代码示例 -->
    <div class="demo-section">
      <h3>代码示例</h3>

      <div class="code-example">
        <h4>1. shallowRef 和 shallowReactive</h4>
        <CodeBlock :code="shallowRefExampleCode" language="javascript"></CodeBlock>

        <h4>2. markRaw 和 toRaw</h4>
        <CodeBlock :code="markRawExampleCode" language="javascript"></CodeBlock>

        <h4>3. 常量定义</h4>
        <h5>适用场景示例</h5>
        <CodeBlock :code="scenariosExampleCode" language="javascript"></CodeBlock>

        <h5>错误使用示例</h5>
        <CodeBlock :code="commonMistakesExampleCode" language="javascript"></CodeBlock>
      </div>
    </div>
  </div>
</template>

<style scoped>
.reactive-advanced-demo {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.demo-title {
  text-align: center;
  margin-bottom: 10px;
  background: linear-gradient(135deg, #42b983 0%, #35495e 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.demo-description {
  text-align: center;
  margin-bottom: 30px;
  color: #666;
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
}

.demo-section {
  margin-bottom: 40px;
  padding: 20px;
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.comparison-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.demo-card {
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  border-left: 4px solid #42b983;
}

.demo-card h4 {
  margin-top: 0;
  color: #35495e;
}

.btn {
  margin-top: 10px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background: #42b983;
  color: white;
  cursor: pointer;
  transition: background-color 0.3s;
}

.btn:hover {
  background: #3aa876;
}

.btn-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}

.btn-primary {
  background: #667eea;
}

.btn-primary:hover {
  background: #5a67d8;
}

.btn-warning {
  background: #ecc94b;
  color: #2d3748;
}

.btn-warning:hover {
  background: #d69e2e;
}

.btn-success {
  background: #38a169;
}

.btn-success:hover {
  background: #2f855a;
}

.hint {
  color: #666;
  font-style: italic;
  margin-top: 10px;
}

.performance-results {
  margin-top: 20px;
}

.performance-table {
  width: 100%;
  border-collapse: collapse;
}

.performance-table th,
.performance-table td {
  padding: 10px;
  text-align: left;
  border-bottom: 1px solid #e2e8f0;
}

.performance-table th {
  background: #f7fafc;
  font-weight: 600;
}

.scenarios-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.scenario-card {
  padding: 20px;
  background: #f0fff4;
  border-radius: 8px;
  border-left: 4px solid #48bb78;
}

.scenario-api {
  margin-top: 0;
  color: #22543d;
}

.scenario-list {
  margin: 10px 0 0;
  padding-left: 20px;
}

.scenario-list li {
  margin-bottom: 8px;
  color: #2d3748;
}

.mistakes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.mistake-card {
  padding: 20px;
  background: #fffaf0;
  border-radius: 8px;
  border-left: 4px solid #ed8936;
}

.mistake-card h4 {
  margin-top: 0;
  color: #744210;
}

.mistake-content {
  margin-top: 10px;
}

.mistake-text {
  color: #c53030;
  margin-bottom: 8px;
}

.solution-text {
  color: #2f855a;
}

.best-practices {
  margin-top: 20px;
}

.best-practices ul {
  padding-left: 20px;
}

.best-practices li {
  margin-bottom: 10px;
  color: #2d3748;
  line-height: 1.6;
}

.best-practices code {
  background: #e2e8f0;
  padding: 2px 4px;
  border-radius: 4px;
  font-family: 'Consolas', 'Monaco', monospace;
}

.code-example {
  margin-top: 20px;
}

.code-example h4 {
  margin-top: 20px;
  margin-bottom: 10px;
  color: #35495e;
}

.code-example pre {
  background: #f8f9fa;
  padding: 16px;
  border-radius: 8px;
  overflow-x: auto;
  border: 1px solid #e2e8f0;
}

.code-example code {
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 14px;
  color: #2d3748;
}

@media (max-width: 768px) {

  .comparison-grid,
  .scenarios-grid,
  .mistakes-grid {
    grid-template-columns: 1fr;
  }

  .demo-section {
    padding: 15px;
  }
}
</style>